home *** CD-ROM | disk | FTP | other *** search
/ SuperHack / SuperHack CD.bin / Hack / MISC / BRUTESRC.ZIP / PWC.C
Encoding:
Text File  |  1990-08-10  |  13.5 KB  |  558 lines

  1. /*
  2.  * pwc -- password cracker
  3.  *
  4.  * pwc is a brute force password cracking program.  It reads a list of
  5.  * /etc/passwd entries from the password file argument and compares
  6.  * the password field against the contents of the remaining file arguments.
  7.  * Good pattern files are the dictionary files in /usr/lib/dict, lists of
  8.  * first names from the GECOS field, single letters and numbers,
  9.  * license plates, etc.
  10.  *
  11.  * usage: pwc [-d] [-v] [-i] passwd_file file1 file2
  12.  *
  13.  * -d    issue debugging information
  14.  *
  15.  * -v    verbose.  Print intermediate information as cracking proceeds
  16.  *
  17.  * -i    identify and print usage message
  18.  */
  19.  
  20. char *Copyright_Legend[] = {
  21.  " Written by Paul Pomes, University of Illinois, Computing Services Office",
  22.  " Copyright (C) 1986 by Paul Pomes and the University of Illinois Board",
  23.  " of Trustees",
  24.  " ",
  25.  " This program is distributed in the hope that it will be useful,",
  26.  " but without any warranty.  No author or distributor accepts",
  27.  " responsibility to anyone for the consequences of using it or for",
  28.  " whether it serves any particular purpose or works at all, unless",
  29.  " s/he says so in writing.",
  30.  " ",
  31.  " Everyone is granted permission to copy, modify and redistribute",
  32.  " this program under the following conditions:",
  33.  " ",
  34.  "    Permission is granted to anyone to make or distribute copies",
  35.  "    of program source code, either as received or modified, in any",
  36.  "    medium, provided that all copyright notices, permission and",
  37.  "    nonwarranty notices are preserved, and that the distributor",
  38.  "    grants the recipient permission for further redistribution as",
  39.  "    permitted by this document, and gives him and points out to",
  40.  "    him an exact copy of this document to inform him of his rights.",
  41.  " ",
  42.  "    Permission is granted to distribute this program in compiled",
  43.  "    or executable form under the same conditions applying for",
  44.  "    source code, provided that either",
  45.  "    A. it is accompanied by the corresponding machine-readable",
  46.  "       source code, or",
  47.  "    B. it is accompanied by a written offer, with no time limit,",
  48.  "       to give anyone a machine-readable copy of the corresponding",
  49.  "       source code in return for reimbursement of the cost of",
  50.  "       distribution.  This written offer must permit verbatim",
  51.  "       duplication by anyone.",
  52.  "    C. it is distributed by someone who received only the",
  53.  "       executable form, and is accompanied by a copy of the",
  54.  "       written offer of source code which he received along with it.",
  55.  " ",
  56.  " In other words, you are welcome to use, share and improve this",
  57.  " program.  You are forbidden to forbid anyone else to use, share",
  58.  " and improve what you give them.   Help stamp out software-hoarding!",
  59.  " ",
  60.  " UUCP:     {ihnp4,pur-ee,convex}!uiucdcs!uiucuxc!paul",
  61.  " ARPANET:  paul%uxc@a.cs.uiuc.edu   CSNET: paul%uxc@uiuc.csnet",
  62.  " ICBMS:    88 13 N / 40 07 W",
  63.  " US Mail:  Univ of Illinois, CSO, 1304 W Springfield Ave, Urbana, IL  61801",
  64.  0
  65. };
  66.  
  67. /*
  68.  * $Log:    pwc.c,v $
  69.  * Revision 1.1  86/08/26  15:55:23  paul
  70.  * Initial revision
  71.  * 
  72.  */
  73.  
  74. #ifndef lint
  75. static char    RcsId[] = "$Header: pwc.c,v 1.1 86/08/26 15:55:23 paul Exp $";
  76. #endif
  77.  
  78. #include    <stdio.h>
  79. #include    <strings.h>
  80. #include    <ctype.h>
  81. #include    <pwd.h>
  82.  
  83. #define        equal(s1, s2)    (strcmp (s1, s2) == 0)
  84. #define        skipline(f)    while (getc (f) != '\n')
  85.  
  86. #define        PROC                /* null; easy to find procs */
  87. #define        FALSE        0
  88. #define        TRUE        1
  89. #define        CHNULL        ('\0')
  90. #define        CPNULL        ((char *) NULL)
  91. #define        FILENULL    ((FILE *) NULL)
  92. #define        REG        register
  93. #define        BMASK        0377
  94.  
  95. #define        MAXFILE        15
  96.  
  97. /*
  98.  * Miscellaneous global values:
  99.  */
  100.  
  101. char *usage[] = {
  102.     "usage: %s [-d] [-v] [-i] passwd_file [file1] [file2 ...]",
  103.     CPNULL
  104. };
  105.  
  106. /* how program was invoked (argv[0]) for error messages */
  107. char        *myname;
  108.  
  109. /* debug messages printed if set (-d) */
  110. int        dflag = FALSE;
  111.  
  112. /* print informational messages every so often (-v) */
  113. int        vflag = FALSE;
  114.  
  115. /* external functions */
  116. extern char    *fcrypt ();
  117.  
  118. /* internal functions */
  119. char        *getstr ();
  120.  
  121. PROC main (argc, argv)
  122. int    argc;
  123. char    **argv;
  124. {
  125.     extern int    optind;        /* from getopt () */
  126.     extern char    *optarg;    /* from getopt () */
  127.     int        option;        /* option "letter" */
  128.     int        i;        /* counters */
  129.     int        done = 0;    /* found a login match */
  130.     REG FILE    *filep;        /* open input file */
  131.     char        *pw_file = CPNULL;    /* name to use */
  132.     char        pattern[200];    /* word patterns from file */
  133.     char        *ciphered;    /* result from fcrypt () */
  134.     char        *cp, *cp2;
  135.     REG struct passwd    *pwp;    /* fast pointer to passwd struct */
  136.     FILE        *pat_fp[MAXFILE];    /* pattern file pointers */
  137.     char        *indexm();
  138.  
  139.     /*
  140.      * BASENAME:  Full string, or past '/' if any:
  141.      */
  142.  
  143.     myname = ((myname = rindex (*argv, '/')) == CPNULL) ? *argv : (myname + 1);
  144.  
  145.     /*
  146.      * PARSE ARGUMENTS:
  147.      */
  148.  
  149.     while ((option = getopt (argc, argv, "dvi")) != EOF) {
  150.         switch (option) {
  151.             case 'd':
  152.             dflag++;
  153.             fprintf (stderr, "%s: dflag = %d\n", myname, dflag);
  154.             break;
  155.  
  156.             case 'v':
  157.             vflag++;
  158.             break;
  159.  
  160.             case 'i':
  161.             Usage (1);
  162.             break;
  163.  
  164.             default:
  165.             Usage (0);
  166.         }
  167.     }
  168.     argc -= optind;            /* skip options */
  169.     argv += optind;
  170.  
  171.     if (argc < 1)             /* no file names */
  172.         Error ("No password file specified");
  173.     pw_file = *argv;
  174.     argc--; argv++;
  175.     if (dflag)
  176.         fprintf (stderr, "password file is %s\n", pw_file);
  177.     setlinebuf (stdout);
  178.  
  179.     /*
  180.      * open the pattern files and assign stream pointers in pat_fp.
  181.      * when stepping through the files, the register variable filep
  182.      * will be what's referenced.  care must be taken to set fp_pat[n]
  183.      * back to what filep is before rewind the file and going on to
  184.      * fp_pat[n+1].
  185.      */
  186.  
  187.     if (argc < 1)             /* no file names */
  188.         pat_fp[0] = FILENULL;
  189.     else {
  190.         for (i = 0; i < MAXFILE && argc > 0; i++, argc--, argv++) {
  191.             if (dflag)
  192.                 fprintf (stderr, "%d opening %s\n", i, *argv);
  193.             if ((pat_fp[i] = fopen (*argv, "r")) == FILENULL)
  194.                 Error ("can't open file \"%s\" to read it", *argv);
  195.         }
  196.         pat_fp[i] = FILENULL;
  197.         if (i == MAXFILE)
  198.             fprintf (stderr, "%s: too many pattern files.  files after %s ignored\n",
  199.                 myname, *(--argv));
  200.     }
  201.  
  202.     /* set the password file name for use by getpwent */
  203.  
  204.     setpwfile (pw_file);
  205.     setpwent ();
  206.  
  207.     init_des();
  208.  
  209.     /*
  210.      * two nested loops do the real work.  outermost loop steps through
  211.      * password entries.  next loop works through pat_fp array of FILE
  212.      * descriptors.  innermost loop works through each file issuing
  213.      * calls to fcrypt ().
  214.      */
  215.  
  216.     while ((pwp = getpwent()) != NULL) {
  217.         done = 0;
  218.         printf ("%.8s", pwp->pw_name);
  219.         (void) fflush (stdout);
  220.         if (*pwp->pw_name == 'U') {
  221.             printf("\t- UUCP account, skipping\n");
  222.             fflush(stdout);
  223.             continue;
  224.         }
  225.         if (*pwp->pw_passwd == '\0') {
  226.             printf("\t- Null password (shell is %s)\n",
  227.                 pwp->pw_shell);
  228.             continue;
  229.         }
  230.         if (equal (pwp->pw_passwd, "*")) {
  231.             printf("\n");
  232.             continue;
  233.         }
  234.         /*
  235.          * Try the user's login name
  236.          */
  237.         *pattern = '\0';
  238.         do {
  239.             (void)strcat(pattern, pwp->pw_name);
  240.             if (uandltry(pwp, pattern)) {
  241.                 done++;
  242.                 break;
  243.             }
  244.         } while (strlen(pattern) < 8);
  245.         if (done)
  246.             continue;
  247.  
  248.         /*
  249.          * Try names from the gecos field
  250.          */
  251.         strcpy(pattern, pwp->pw_gecos);
  252.         cp = pattern;
  253.         for (;;) {
  254.             if ((cp2 = indexm(cp, " ,;")) == NULL)
  255.                 cp2 = pattern + strlen(pwp->pw_gecos) - 1;
  256.             else
  257.                 *cp2 = '\0';
  258.             if (uandltry(pwp,cp)) {
  259.                 done++;
  260.                 break;
  261.             }
  262.             cp = ++cp2;
  263.         }
  264.         if (done)
  265.             continue;
  266.  
  267.         /*
  268.          * Try all single letters
  269.          * (try digits too .  --Seth)
  270.          */
  271.         pattern[1] = '\0';
  272.         for (pattern[0]='a'; pattern[0] <= 'z'; pattern[0]++)
  273.             if (try(pwp,pattern)) {
  274.                 done++;
  275.                 break;
  276.             }
  277.         for (pattern[0]='A'; pattern[0] <= 'Z'; pattern[0]++)
  278.             if (try(pwp,pattern)) {
  279.                 done++;
  280.                 break;
  281.             }
  282.         for (pattern[0]='0'; pattern[0] <= '9'; pattern[0]++)
  283.             if (try(pwp,pattern)) {
  284.                 done++;
  285.                 break;
  286.             }
  287.         if (done)
  288.             continue;
  289.         for (i = 0, filep = pat_fp[i];
  290.             filep != FILENULL; i++, filep = pat_fp[i]) {
  291.             while (getstr (pattern, 8, filep) != CPNULL) {
  292.                 ciphered = fcrypt (pattern, pwp->pw_passwd);
  293.                 if (dflag > 1)
  294.                     fprintf(stderr, "  Testing =%s=, got =%s=\n", pattern, ciphered);
  295.                 if (equal (ciphered, pwp->pw_passwd)) {
  296.                     try (pwp, pattern);
  297.                     done++;
  298.                     break;
  299.                 }
  300.             }
  301.             rewind (filep);
  302.             if (done)
  303.                 break;
  304.         }
  305.         if (! done)
  306.             putchar ('\n');
  307.     }
  308.     exit (0);
  309. } /* main */
  310.  
  311. /*
  312.  * Usage -- print how to use message
  313.  *
  314.  * Print usage messages (char *usage[]) to stderr and exit nonzero.
  315.  * Each message is followed by a newline.
  316.  *
  317.  *    parameters:
  318.  *        full_text    (IN)    prints the copyright statement if set
  319.  *    returns:
  320.  *        none, exit (1)
  321.  *    side effects:
  322.  *        program terminates
  323.  *    deficiencies:
  324.  */
  325.  
  326. PROC Usage (full_text)
  327. int    full_text;
  328. {
  329.     REG int        which = 0;        /* current line */
  330.  
  331.     while (usage[which] != CPNULL) {
  332.         fprintf (stderr, usage[which++], myname);
  333.         putc ('\n', stderr);
  334.     }
  335.     fflush(stdout);
  336.     which = 0;
  337.     if (full_text) {
  338.         while (Copyright_Legend[which] != CPNULL)
  339.             printf ("%s\n", Copyright_Legend[which++]);
  340.     }
  341.     exit (1);
  342. } /* Usage */
  343.  
  344. /*
  345.  * Error -- print error message with program name
  346.  *
  347.  * Print an error message to stderr and exit nonzero.  Message is preceded
  348.  * by "<myname>: " using global char *myname, and followed by a newline.
  349.  *
  350.  *    parameters:
  351.  *        message (IN)    printf format string
  352.  *        arg1-4    (IN)    printf arguments
  353.  *    returns:
  354.  *        none, exit (1)
  355.  *    side effects:
  356.  *        program terminates
  357.  *    deficiencies:
  358.  */
  359.  
  360. /* VARARGS */
  361. PROC Error (message, arg1, arg2, arg3, arg4)
  362. char    *message;
  363. long    arg1, arg2, arg3, arg4;
  364. {
  365.     fprintf (stderr, "%s: ", myname);
  366.     fprintf (stderr, message, arg1, arg2, arg3, arg4);
  367.     putc ('\n', stderr);
  368.     exit (1);
  369. } /* Error */
  370.  
  371. /*
  372.  * Malloc -- a malloc with error checking
  373.  *
  374.  *    parameters:
  375.  *        size    (IN)    number of bytes to get
  376.  *    returns:
  377.  *        (char *) of first char of block, or
  378.  *        calls Error () upon error
  379.  *    side effects:
  380.  *        none
  381.  *    deficiencies:
  382.  */
  383.  
  384. char    *malloc ();
  385. char    *Malloc ();
  386.  
  387. PROC char * Malloc (size)
  388. unsigned    size;    /* bytes to get */
  389. {
  390.     char    *cp;    /* pointer to memory */
  391.  
  392.     if ((cp = malloc (size)) == CPNULL)
  393.         Error ("malloc %d bytes failed", size);
  394.     return (cp);
  395. } /* Malloc */
  396.  
  397. /*
  398.  * getstr -- get a string of length n or up to a new-line from a file
  399.  *
  400.  *    parameters:
  401.  *        s    (IN/OUT) char array to place string into
  402.  *        n    (IN)     maximum number of characters to get
  403.  *        iop    (IN/OUT) FILE descriptor
  404.  *    returns:
  405.  *        (char *) of first char of block, or
  406.  *        calls Error () upon error
  407.  *    side effects:
  408.  *        none
  409.  *    deficiencies:
  410.  */
  411.  
  412. PROC char * getstr (s, n, iop)
  413. char    *s;
  414. int    n;
  415. register FILE *iop;
  416. {
  417.     register c;
  418.     register char *cs;
  419.  
  420.     cs = s;
  421.     n++;
  422.     while (--n > 0 && (c = getc (iop)) >= NULL) {
  423.         *cs = c;
  424.         if (c == '\n') {
  425.             *cs = CHNULL;
  426.             break;
  427.         }
  428.         cs++;
  429.     }
  430.     if (c < 0 && cs == s)
  431.         return (CPNULL);
  432.     if (c != '\n')
  433.         while ((c = getc (iop)) != '\n' && c >= 0)
  434.     *cs++ = CHNULL;
  435.     return (s);
  436. } /* getstr */
  437. /*
  438.  * Added by Jacob Gore, March 12, 1987.
  439.  *
  440.  * Finds the pointer of the leftmost occurance within the character string
  441.  * 'string' of any character found within the character string 'chars'.
  442.  *
  443.  * If none of the characters in 'chars' appear in 'string', NULL is retutned.
  444.  *
  445.  */
  446. char *
  447. indexm (string, chars)
  448.     char *string, *chars;
  449. {
  450.     while (*string) {
  451.     if (index(chars, *string) != NULL) {
  452.         return string;
  453.     }
  454.     string++;
  455.     }
  456.     return NULL;
  457. }
  458. /*
  459.  * Stands for "upper and lower" try.  Calls the "real" try, below,
  460.  * with the supplied version of the password, and with
  461.  * an upper and lowercase version of the password. If the user doesn't
  462.  * want to try upper and lower case then we just return after the one
  463.  * check.
  464.  * Written by Craig Leres, modified by Paul Pomes
  465. */
  466.  
  467. uandltry (pwd,guess)
  468. char *guess;
  469. struct passwd *pwd;
  470. {
  471.     register char *cp, *cpx;
  472.     char buf[100];
  473.     int alllower, allupper;
  474.     char *reverse();
  475.  
  476.     alllower = allupper = 1;
  477.  
  478.     if (try(pwd,guess)) return (1); 
  479.     if (try(pwd,(cpx = reverse(guess)))) {
  480.     free (cpx);
  481.     return (1);
  482.     }
  483.     free (cpx);
  484.  
  485.     strcpy (buf, guess);
  486.     cp = buf-1;
  487.     while (*++cp) {
  488.     if (isupper(*cp))
  489.         alllower = 0;
  490.     if (islower(*cp))
  491.         allupper = 0;
  492.     }
  493.  
  494.     if (!allupper) {
  495.     for ( cp=buf; *cp != '\0'; cp++)
  496.         if (islower (*cp))
  497.         *cp += 'A' - 'a';
  498.  
  499.         if (try(pwd,buf)) return (1); 
  500.         if (try(pwd,(cpx = reverse(buf)))) {
  501.         free (cpx);
  502.         return (1);
  503.         }
  504.         free (cpx);
  505.     }
  506.  
  507.     if (!alllower) {
  508.     for ( cp = buf; *cp != '\0'; cp++)
  509.         if (isupper (*cp))
  510.         *cp += 'a' - 'A';
  511.  
  512.     if (try(pwd,buf)) return (1); 
  513.     if (try(pwd,(cpx = reverse(buf)))) {
  514.         free (cpx);
  515.         return (1);
  516.     }
  517.     free (cpx);
  518.     }
  519.     return (0);
  520. }
  521.  
  522. try(pwd,guess)
  523. char *guess;
  524. register struct passwd *pwd;
  525. {
  526.     register char  *cp;
  527.     char   *fcrypt ();
  528.  
  529.     if (! guess || ! *guess) return(0);
  530.     cp = fcrypt (guess, pwd -> pw_passwd);
  531.     if (strcmp (cp, pwd -> pw_passwd))
  532.     return (0);
  533.     printf("\t- Guessed password is %s (shell is %s)\n",
  534.             guess, pwd->pw_shell);
  535.     fflush (stdout);
  536.     return (1);
  537. }
  538. /*
  539.  * reverse a string
  540.  */
  541. char *reverse(str)
  542. char *str;
  543.  
  544. {
  545.     register char *ptr;
  546.     register int len;
  547.     char    *malloc();
  548.  
  549.     if ((ptr = malloc((len = strlen(str))+1)) == NULL)
  550.     return(NULL);
  551.     ptr += len;
  552.     *ptr = '\0';
  553.     while (*str && (*--ptr = *str++))
  554.     ;
  555.     return(ptr);
  556. }
  557.  
  558.